﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CdcSoftware.Pivotal.Applications.Core.Common;
using CdcSoftware.Pivotal.Applications.Core.Data;
using CdcSoftware.Pivotal.Engine;
using CdcSoftware.Pivotal.Engine.Types.ServerTasks;
using CdcSoftware.Pivotal.Applications.Core.Server;
using CdcSoftware.Pivotal.Engine.Types.DataTemplates;
using System.Data;

namespace Pcm.Inventory.Server.FormTasks
{
    public class RE_Stock_Take : AbstractDataTemplateServerTask
    {
        #region Constants

        const string InventoryForSKUAndStorageLocationQueryName = "RE_Inventory for SKU? Storage Location?";
        const string StorageLocationIdFieldName = "Storage_Location_Id";
        const string ProductSKUIdFieldName = "Product_SKU_Id";
        const string ExistingQuantityFieldName = "Existing_Quantity";
        const string StockTakeQuantityFieldName = "Stock_Take_Quantity";
        const string QuantityActualFieldName = "Quantity_Actual";
        const string VarianceFieldName = "Variance";
        const string ProductIdFieldName = "Product_Id";
        const string Status = "Status";
        const string REInventoryTable = "RE_Inventory";
        const string QuantityTheoreticalFieldName = "Quantity_Theoretical";
        const string stockDetailSecondary = "RE_Stock_Take_Detail_Stock_Take_Id";
        const string StockDetailsWithStockId = "RE_Stock Details with Stock Id?";

        #endregion


        public RE_Stock_Take()
        {
        }




        #region Abstract Data Template Methods

        protected override DataSet LoadData(DataTemplate dataTemplate, Id rowId, ParameterList parameters)
        {
            try
            {
                return base.LoadData(dataTemplate, rowId, parameters);
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        protected override Id AddData(DataTemplate dataTemplate, DataSet data, ParameterList parameters)
        {
            try
            {
                return base.AddData(dataTemplate, data, parameters);
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        #endregion


        #region Private methods

        private void CreateInventoryMovement(object productId, object productSKUId, object storageLocation, Int16 variance)
        {
            try
            {
                const string InventoryforSKUAndStorageLocation = "RE_Inventory for SKU? Storage Location?";
                object inventoryId = DBNull.Value;
                DataTable inventoryDT = null;

                DataTable inventoryMovement = DefaultDataAccess.GetNewDataTable("RE_Inventory_Movement",
                                                new string[] { "Direction", "Reason", "Movement_Date", "Ref_Inventory_Trnsfr_Id", "Storage_Location_Id",
                                                                "Product_Id",ProductSKUIdFieldName,"Quantity","Inventory_Id"});

                string direction = "Skip";
                DataRow dRow = inventoryMovement.NewRow();
                if (variance < 0) //this happens when the stock is more than the inventory quantity
                {
                    dRow["Direction"] = "Add";
                    direction = "Add";
                }
                else if (variance > 0)//Its when the stock is less than inventory quantity
                {
                    dRow["Direction"] = "Subtract";
                    direction = "Subtract";
                }

                if(direction == "Skip") // Doesn't create Movement if there is no variance
                    return;

                if (productSKUId != DBNull.Value && storageLocation != DBNull.Value)
                {
                    inventoryDT = this.DefaultDataAccess.GetDataTable(InventoryforSKUAndStorageLocation, new object[] { productSKUId, storageLocation },
                                                                       new string[] { "RE_Inventory_Id", "Quantity_Actual" });
                    if (inventoryDT != null)
                    {
                        if (inventoryDT.Rows.Count > 0)
                        {
                            inventoryId = inventoryDT.Rows[0]["RE_Inventory_Id"];
                            //Update Inventory 
                            if (direction == "Add")
                            {
                                inventoryDT.Rows[0]["Quantity_Actual"] = TypeConvert.ToInt32(inventoryDT.Rows[0]["Quantity_Actual"]) + Math.Abs(variance);
                            }
                            else if (direction == "Subtract")
                            {
                                inventoryDT.Rows[0]["Quantity_Actual"] = TypeConvert.ToInt32(inventoryDT.Rows[0]["Quantity_Actual"]) - Math.Abs(variance);
                            }
                            this.DefaultDataAccess.SaveDataTable(inventoryDT);
                        }
                    }
                }
                dRow["Movement_Date"] = DateTime.Now;
                dRow[ProductIdFieldName] = productId;
                dRow[ProductSKUIdFieldName] = productSKUId;
                dRow["Quantity"] = Math.Abs(variance);
                dRow["Inventory_Id"] = inventoryId;
                dRow["Storage_Location_Id"] = storageLocation;
                dRow["Reason"] = "Stock Take";
                inventoryMovement.Rows.Add(dRow);

                DefaultDataAccess.SaveDataTable(inventoryMovement);
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }

        #endregion

        #region Task Execute Methods



        [TaskExecute]
        public virtual void ProcessStock(object stockTakeId)
        {
            try
            {
                DataTable stockDetails = null;

                stockDetails = DefaultDataAccess.GetDataTable(StockDetailsWithStockId, Id.Create(stockTakeId),
                                            new string[] {ProductIdFieldName,ProductSKUIdFieldName,StorageLocationIdFieldName,
                                                          VarianceFieldName });
                if (stockDetails != null)
                {
                    if (stockDetails.Rows.Count > 0)
                    {
                        for (int i = 0; i < stockDetails.Rows.Count; i++)
                        {
                            this.CreateInventoryMovement(stockDetails.Rows[i][ProductIdFieldName], stockDetails.Rows[i][ProductSKUIdFieldName],
                                stockDetails.Rows[i][StorageLocationIdFieldName], TypeConvert.ToInt16(stockDetails.Rows[i][VarianceFieldName]));
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                throw new PivotalApplicationCoreException(exc.Message, exc);
            }
        }
        #endregion
    }
}
